package org.simplextensions.registry;

import java.lang.annotation.Annotation;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.simplextensions.registry.phaselisteners.IDependencyLocator;

@org.simplextensions.annotations.ExtensionPoint(id = IDependencyLocator.EP_ID, extensionClass = IDependencyLocator.class)
public class DependencyLocatorRegistry implements IDependencyLocatorRegistry, IExtensionPoint {
	private static final Log log = LogFactory.getLog(DependencyLocatorRegistry.class);

	private Map<Class<? extends Annotation>, IDependencyLocator> supportedAnnotations = new HashMap<Class<? extends Annotation>, IDependencyLocator>();

	private IExtensionRegistry extensionRegistry;

	public void initialize(ExtensionPoint extensionPoint) {
		this.extensionRegistry = extensionPoint.getExtensionRegistry();
		Collection<Extension> extensions = extensionPoint.getActiveExtensions();
		for (Extension e : extensions) {
			if (IDependencyLocator.class.isAssignableFrom(e.getClazz())) {
				Class<?> annotationClass = e.getPropertyValue(IDependencyLocator.ANNOTATION).getClassValue();
				addSupportedAnnotation((Class<? extends Annotation>) annotationClass, (IDependencyLocator) e.getExecutable());
			}
		}
	}

	private void addSupportedAnnotation(Class<? extends Annotation> annotation, IDependencyLocator serviceLocator) {
		if (supportedAnnotations.keySet().contains(annotation)) {
			// TODO: consider throwing an exception
			log.error(serviceLocator.getClass().getName() + " error. Annotation" + annotation.getName() + " already register by class "
					+ supportedAnnotations.get(serviceLocator).getClass().getCanonicalName());
		} else {
			serviceLocator.init(this);
			supportedAnnotations.put(annotation, serviceLocator);
		}
	}

	public IDependencyLocator findDependencyLocator(Class<? extends Annotation> annotation) {
		return supportedAnnotations.get(annotation);
	}

	public IExtensionRegistry getExtensionRegistry() {
		return this.extensionRegistry;
	}

	public Set<Class<? extends Annotation>> getSupportedAnnotations() {
		return supportedAnnotations.keySet();
	}
}
